package cn.xlbweb.cli.service.impl;

import cn.xlbweb.cli.mapper.*;
import cn.xlbweb.cli.model.*;
import cn.xlbweb.cli.common.ServerResponse;
import cn.xlbweb.cli.common.TableResponse;
import cn.xlbweb.cli.common.TreeResponse;
import cn.xlbweb.cli.pojo.dto.DeleteRoleDTO;
import cn.xlbweb.cli.pojo.dto.InsertRoleDTO;
import cn.xlbweb.cli.pojo.dto.ListRoleDTO;
import cn.xlbweb.cli.pojo.dto.UpdateRoleDTO;
import cn.xlbweb.cli.pojo.vo.ListAssignVO;
import cn.xlbweb.cli.pojo.vo.ListAuthorizeVO;
import cn.xlbweb.cli.pojo.vo.ListRoleNameVO;
import cn.xlbweb.cli.pojo.vo.ListRoleVO;
import cn.xlbweb.cli.service.IRoleService;
import cn.xlbweb.cli.shiro.CliRealm;
import cn.xlbweb.cli.util.CliUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: bobi
 * @date: 2019-09-16 23:17
 * @description:
 */
@Service
@Slf4j
public class RoleServiceImpl implements IRoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Override
    public TableResponse listRole(ListRoleDTO listRoleDTO) {
        log.info("listRole() start...");
        // 构造查询条件
        RoleExample roleExample = new RoleExample();
        if (StringUtils.isNotBlank(listRoleDTO.getName())) {
            roleExample.createCriteria().andNameLike("%" + listRoleDTO.getName() + "%");
        }

        // 构建分页
        PageHelper.startPage(listRoleDTO.getCurrentPage(), listRoleDTO.getPageSize());
        List<Role> roleList = roleMapper.selectByExample(roleExample);
        PageInfo<Role> rolePageInfo = new PageInfo<>(roleList);

        // 构建Vo
        List<ListRoleVO> listRoleVO = new ArrayList<>();
        roleList.forEach(role -> {
            ListRoleVO roleVo = new ListRoleVO();
            CliUtils.copyProperties(role, roleVo);
            // 创建者
            User createUser = userMapper.selectByPrimaryKey(role.getCreateUserId());
            roleVo.setCreateUsername(createUser.getUsername());
            // 更新者
            User updateUser = userMapper.selectByPrimaryKey(role.getUpdateUserId());
            roleVo.setUpdateUsername(updateUser.getUsername());
            listRoleVO.add(roleVo);
        });
        log.info("listRole() end...");
        return TableResponse.success(rolePageInfo.getTotal(), listRoleVO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse insertRole(InsertRoleDTO insertRoleDTO) {
        if (getRoleByName(insertRoleDTO.getName()) != null) {
            return ServerResponse.error("角色名已存在");
        }

        Role role = new Role();
        CliUtils.copyProperties(insertRoleDTO, role);
        // 创建人
        role.setCreateUserId(CliUtils.getCurrentUserId());
        // 更新人
        role.setUpdateUserId(CliUtils.getCurrentUserId());
        int count = roleMapper.insertSelective(role);
        if (count > 0) {
            return ServerResponse.success("添加成功");
        }
        return ServerResponse.error("插入失败");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse updateRole(UpdateRoleDTO updateRoleDTO) {
        Role dbRole = roleMapper.selectByPrimaryKey(updateRoleDTO.getId());
        if (!StringUtils.equals(updateRoleDTO.getName(), dbRole.getName())
                && getRoleByName(updateRoleDTO.getName()) != null) {
            return ServerResponse.error("角色名已存在");
        }

        Role role = new Role();
        CliUtils.copyProperties(updateRoleDTO, role);
        // 更新人
        role.setUpdateUserId(CliUtils.getCurrentUserId());
        int count = roleMapper.updateByPrimaryKeySelective(role);
        if (count > 0) {
            return ServerResponse.success("更新成功");
        }
        return ServerResponse.error("更新失败");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServerResponse deleteRole(DeleteRoleDTO deleteRoleDTO) {
        // 删除该角色所拥有的所有权限
        deleteRolePermission(deleteRoleDTO.getIds());
        // 构建删除条件
        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andIdIn(CliUtils.getIdList(deleteRoleDTO.getIds()));
        // 删除角色
        int count = roleMapper.deleteByExample(roleExample);
        if (count > 0) {
            return ServerResponse.success("删除成功");
        }
        return ServerResponse.error("删除失败");
    }

    @Override
    public ServerResponse listRoleName() {
        List<Role> roles = roleMapper.selectByExample(null);
        List<ListRoleNameVO> vos = new ArrayList<>();
        roles.forEach(item -> {
            ListRoleNameVO vo = new ListRoleNameVO();
            vo.setId(item.getId());
            vo.setLabel(item.getName());
            vos.add(vo);
        });
        return ServerResponse.success("查询成功", vos);
    }

    @Override
    public TreeResponse listAuthorize(Integer roleId) {
        // 查询所有权限
        List<Permission> permissionList = permissionMapper.selectByExample(null);
        // 构建Vo
        List<ListAuthorizeVO> listPermissionsVOList = xxx(permissionList, 0);
        // 查询该角色所拥有的全部权限集合
        RolePermissionExample rolePermissionExample = new RolePermissionExample();
        rolePermissionExample.createCriteria().andRoleIdEqualTo(roleId);
        List<RolePermission> rolePermissionList = rolePermissionMapper.selectByExample(rolePermissionExample);
        List<Integer> roleHaveIds = new ArrayList<>();
        for (RolePermission rolePermission : rolePermissionList) {
            roleHaveIds.add(rolePermission.getPermissionId());
        }
        return TreeResponse.success(roleHaveIds, listPermissionsVOList);
    }

    @Override
    public ServerResponse authorize(Integer roleId, String permissionIds) {
        // 删除该角色所拥有的所有权限
        RolePermissionExample rolePermissionExample = new RolePermissionExample();
        rolePermissionExample.createCriteria().andRoleIdEqualTo(roleId);
        rolePermissionMapper.deleteByExample(rolePermissionExample);
        // 赋权
        for (Integer permissionId : CliUtils.getIdList(permissionIds)) {
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permissionId);
            Role role = roleMapper.selectByPrimaryKey(roleId);
            Permission permission = permissionMapper.selectByPrimaryKey(permissionId);
            rolePermission.setRemarks(role.getName() + "-" + permission.getName());
            rolePermissionMapper.insertSelective(rolePermission);
        }
        // 清空所有登录用户权限缓存
        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        CliRealm realm = (CliRealm) rsm.getRealms().iterator().next();
        realm.clearAllCachedAuthorization();
        return ServerResponse.success("赋权成功");
    }

    @Override
    public ServerResponse listAssign(Integer roleId) {
        // 所有用户信息
        List<User> userList = userMapper.selectByExample(null);
        List<Map<String, Object>> users = new ArrayList<>();
        userList.forEach(user -> {
            Map<String, Object> authUser = new HashMap<>(4);
            authUser.put("id", user.getId());
            authUser.put("username", user.getUsername());
            users.add(authUser);
        });

        // 该角色已授权用户信息
        UserRoleExample userRoleExample = new UserRoleExample();
        userRoleExample.createCriteria().andRoleIdEqualTo(roleId);
        List<UserRole> userRoleList = userRoleMapper.selectByExample(userRoleExample);
        List<Integer> authIds = userRoleList.stream().map(userRole -> userRole.getUserId()).collect(Collectors.toList());

        ListAssignVO listAssignVO = ListAssignVO.builder().users(users).authIds(authIds).build();
        return ServerResponse.success(listAssignVO);
    }

    @Override
    public ServerResponse assign(Integer roleId, String userIds) {
        // 清空此角色所拥有的用户
        UserRoleExample userRoleExample = new UserRoleExample();
        userRoleExample.createCriteria().andRoleIdEqualTo(roleId);
        userRoleMapper.deleteByExample(userRoleExample);

        // 为此角色添加新用户
        Role role = roleMapper.selectByPrimaryKey(roleId);
        if (StringUtils.isNotBlank(userIds)) {
            List<Integer> userIdList = CliUtils.strToIntegerList(userIds);
            if (!userIdList.isEmpty()) {
                userIdList.forEach(userId -> {
                    UserRole userRole = new UserRole();
                    userRole.setRoleId(roleId);
                    userRole.setUserId(userId);
                    User user = userMapper.selectByPrimaryKey(userId);
                    userRole.setRemarks(role.getName() + " - " + user.getUsername());
                    userRoleMapper.insertSelective(userRole);
                });
            }
        }
        return ServerResponse.success("分配成功");
    }

    private Role getRoleByName(String name) {
        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andNameEqualTo(name);
        List<Role> roleList = roleMapper.selectByExample(roleExample);
        return !roleList.isEmpty() ? roleList.get(0) : null;
    }

    private void deleteRolePermission(String roleIds) {
        List<Integer> idList = CliUtils.getIdList(roleIds);
        RolePermissionExample rolePermissionExample = new RolePermissionExample();
        rolePermissionExample.createCriteria().andRoleIdIn(idList);
        int count = rolePermissionMapper.deleteByExample(rolePermissionExample);
        log.info("成功删除{}条角色的权限信息", count);
    }

    public List<ListAuthorizeVO> xxx(List<Permission> permissionList, Integer parentId) {
        List<ListAuthorizeVO> authorizes = new ArrayList<>();
        for (Permission permission : permissionList) {
            if (permission.getPid().equals(parentId)) {
                ListAuthorizeVO authorize = new ListAuthorizeVO();
                authorize.setId(permission.getId());
                authorize.setLabel(permission.getName());
                authorizes.add(authorize);
            }
        }
        for (ListAuthorizeVO authorize : authorizes) {
            authorize.setChildren(xxx(permissionList, authorize.getId()));
        }
        return authorizes;
    }
}
